# This script is used to find out how heavy a given machine thinks
# that a couple of tasks are.

from __future__ import with_statement
from threading import Thread
from time import sleep, time
from thread import allocate_lock
import sys

class CPUInfo(object):
    def __init__(self, cores = 1, fake_measure = None, measure_period = 0.5):
        self.__cores = cores
        if fake_measure:
            self.__int_perf = fake_measure
            self.__float_perf = fake_measure
        else:
            self.measure_cpu_performance(measure_period)

    def measure_cpu_performance(self, measure_period = 0.5):
        measurer = BogomipsMeasurer()
        measurer.start()
        int_perf, float_perf = measurer.measure(measure_period)
        self.__int_perf = int(int_perf)
        self.__float_perf = int(float_perf)
        measurer.shutdown()
        del measurer
    
    def cores(): #@NoSelf
        def fget(self):
            return self.__cores
        def fset(self, value):
            self.__cores = value
        return locals()
    cores = property(**cores())

    def int_perf(): #@NoSelf
        def fget(self):
            return self.__int_perf
        return locals()
    int_perf = property(**int_perf())

    def float_perf(): #@NoSelf
        def fget(self):
            return self.__float_perf
        return locals()
    float_perf = property(**float_perf())

class BogomipsMeasurer(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.stop_thread = False
        self.start_measurement = False
        self.stop_measurement = False
        self.int_measure = 0.0
        self.float_measure = 0.0
        self.daemon = True
        self.signal = allocate_lock()
        self.signal.acquire()
        
    def run(self):
        # Wait for someone to tell you to start.
        while not self.stop_thread:
            while not self.start_measurement:
                if self.stop_thread:
                    return 0
                sleep(0.01)
        
            # Measure integer performance. 
            start_int = time()
            i = 0
            x = 0
            while not self.stop_measurement:
                x += 42
                x /= 7
                x *= 6
                x -= 36
                i += 1
            stop_int = time()
            if self.stop_thread:
                return 0
            try:
                self.int_measure = float(i)/(stop_int-start_int)
            except:
                self.int_measure = 0.0
                
            # Measure float performance.
            self.stop_measurement = False
            start_float = time()
            i = 0
            x = 0.0
            while not self.stop_measurement:
                x += 49.7
                x /= 7.1
                x *= 6.9
                x -= 48.3
                i += 1
            stop_float = time()
            if self.stop_thread:
                return 0
            try:
                self.float_measure = float(i)/(stop_float-start_float)
            except:
                self.float_measure = 0.0
        
            # Return to being idle.
            self.start_measurement = False
            self.stop_measurement = False
            
            # Signal that data is ready.
            self.signal.release()
        
    def measure(self, interval=0.10):
        self.start_measurement = True
        sleep(interval)
        self.stop_measurement = True
        sleep(interval)
        self.stop_measurement = True
        self.signal.acquire()
        return (self.int_measure, self.float_measure)
    
    def shutdown(self):
        self.stop_thread = True
        self.stop_measurement = True

verbose = False
if '-d' in sys.argv:
    verbose = True

# Measure cpu strength.
if verbose: print 'Measuring CPU strength'
cpu = CPUInfo(measure_period=2)
strength = (cpu.int_perf + cpu.float_perf)/2
if verbose: print 'done, result=', strength, '(int =%f, float = %f)'%(cpu.int_perf, cpu.float_perf)

# Time some methods to see how long they take.
def sharpen(image, factor):
    from PIL import Image, ImageEnhance
    from StringIO import StringIO
    sio = StringIO(image)
    pil_image = Image.open(sio)
    factor = 1.0 + float(factor)
    sharpened_image = ImageEnhance.Sharpness(pil_image).enhance(factor)
    sio = StringIO()
    sharpened_image.save(sio, pil_image.format, quality=95)
    return sio.getvalue()

def brightness(image, factor):
    from PIL import Image, ImageEnhance
    from StringIO import StringIO
    sio = StringIO(image)
    pil_image = Image.open(sio)
    sharpened_image = ImageEnhance.Brightness(pil_image).enhance(factor)
    sio = StringIO()
    sharpened_image.save(sio, pil_image.format, quality=95)
    return sio.getvalue()

if verbose: print 'measuring sharpen'
with open(sys.argv[1]) as infile:
    image = infile.read()
start = time()
sharpen(image, 0.75)
stop = time()
brightness(image, 0.75)
full_stop = time()
if verbose: 
    print 'sharpen time =', stop-start, ' cost =', strength*(stop-start)
    print 'brightness time =', full_stop-stop, ' cost =', strength*(full_stop-stop)
else: 
    print strength, strength*(stop-start), strength*(full_stop-stop)
